﻿using Sidvall.Serialization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace Sidvall.UI.Wpf.Controls
{
    public partial class CheckBoxListControl : UserControl
    {
        #region Public Members

        #region DisplayMemberPath

        public static readonly System.Windows.DependencyProperty DisplayMemberPathProperty = System.Windows.DependencyProperty.Register(nameof(DisplayMemberPath), typeof(string), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(null, System.Windows.FrameworkPropertyMetadataOptions.None, null, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public string DisplayMemberPath
        {
            get
            {
                return GetValue(DisplayMemberPathProperty) as string;
            }
            set
            {
                SetValue(DisplayMemberPathProperty, value);
            }
        }

        #endregion
        #region ItemsSource

        public static readonly System.Windows.DependencyProperty ItemsSourceProperty = System.Windows.DependencyProperty.Register(nameof(ItemsSource), typeof(System.Collections.IEnumerable), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(null, System.Windows.FrameworkPropertyMetadataOptions.None, OnItemsSourcePropertyChanged, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public System.Collections.IEnumerable ItemsSource
        {
            get
            {
                return GetValue(ItemsSourceProperty) as System.Collections.IEnumerable;
            }
            set
            {
                SetValue(ItemsSourceProperty, value);
            }
        }

        #endregion
        #region ItemMargin

        public static readonly System.Windows.DependencyProperty ItemMarginProperty = System.Windows.DependencyProperty.Register(nameof(ItemMargin), typeof(Thickness), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(new Thickness(8, 0, 0, 0), System.Windows.FrameworkPropertyMetadataOptions.None, null, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public Thickness ItemMargin
        {
            get
            {
                return (Thickness)GetValue(ItemMarginProperty);
            }
            set
            {
                SetValue(ItemMarginProperty, value);
            }
        }

        #endregion
        #region ItemOrientation

        public static readonly System.Windows.DependencyProperty ItemOrientationProperty = System.Windows.DependencyProperty.Register(nameof(ItemOrientation), typeof(System.Windows.Controls.Orientation), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(System.Windows.Controls.Orientation.Vertical, System.Windows.FrameworkPropertyMetadataOptions.None, null, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public System.Windows.Controls.Orientation ItemOrientation
        {
            get
            {
                return (System.Windows.Controls.Orientation)GetValue(ItemOrientationProperty);
            }
            set
            {
                SetValue(ItemOrientationProperty, value);
            }
        }

        #endregion
        #region LabelMargin

        public static readonly System.Windows.DependencyProperty LabelMarginProperty = System.Windows.DependencyProperty.Register(nameof(LabelMargin), typeof(Thickness), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(new Thickness(0, 0, 0, 0), System.Windows.FrameworkPropertyMetadataOptions.None, null, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public Thickness LabelMargin
        {
            get
            {
                return (Thickness)GetValue(LabelMarginProperty);
            }
            set
            {
                SetValue(LabelMarginProperty, value);
            }
        }

        #endregion
        #region LabelText

        public static readonly System.Windows.DependencyProperty LabelTextProperty = System.Windows.DependencyProperty.Register(nameof(LabelText), typeof(string), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(null, System.Windows.FrameworkPropertyMetadataOptions.None, OnLabelTextPropertyChanged, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public string LabelText
        {
            get
            {
                return GetValue(LabelTextProperty) as string;
            }
            set
            {
                SetValue(LabelTextProperty, value);
            }
        }

        #endregion
        #region LabelLeftContent

        public static readonly System.Windows.DependencyProperty LabelLeftContentProperty = System.Windows.DependencyProperty.Register(nameof(LabelLeftContent), typeof(object), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(null, System.Windows.FrameworkPropertyMetadataOptions.None, null, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public object LabelLeftContent
        {
            get
            {
                return GetValue(LabelLeftContentProperty);
            }
            set
            {
                SetValue(LabelLeftContentProperty, value);
            }
        }

        #endregion
        #region LabelRightContent

        public static readonly System.Windows.DependencyProperty LabelRightContentProperty = System.Windows.DependencyProperty.Register(nameof(LabelRightContent), typeof(object), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(null, System.Windows.FrameworkPropertyMetadataOptions.None, null, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public object LabelRightContent
        {
            get
            {
                return GetValue(LabelRightContentProperty);
            }
            set
            {
                SetValue(LabelRightContentProperty, value);
            }
        }

        #endregion

        #region IsChecked1

        public static readonly System.Windows.DependencyProperty IsChecked1Property = System.Windows.DependencyProperty.Register(nameof(IsChecked1), typeof(bool?), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(null, System.Windows.FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsChecked1PropertyChanged, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public bool? IsChecked1
        {
            get
            {
                return GetValue(IsChecked1Property) as bool?;
            }
            set
            {
                SetValue(IsChecked1Property, value);
            }
        }

        #endregion
        #region IsChecked2

        public static readonly System.Windows.DependencyProperty IsChecked2Property = System.Windows.DependencyProperty.Register(nameof(IsChecked2), typeof(bool?), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(null, System.Windows.FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsChecked2PropertyChanged, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public bool? IsChecked2
        {
            get
            {
                return GetValue(IsChecked2Property) as bool?;
            }
            set
            {
                SetValue(IsChecked2Property, value);
            }
        }

        #endregion
        #region IsChecked3

        public static readonly System.Windows.DependencyProperty IsChecked3Property = System.Windows.DependencyProperty.Register(nameof(IsChecked3), typeof(bool?), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(null, System.Windows.FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsChecked3PropertyChanged, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public bool? IsChecked3
        {
            get
            {
                return GetValue(IsChecked3Property) as bool?;
            }
            set
            {
                SetValue(IsChecked3Property, value);
            }
        }

        #endregion
        #region IsChecked4

        public static readonly System.Windows.DependencyProperty IsChecked4Property = System.Windows.DependencyProperty.Register(nameof(IsChecked4), typeof(bool?), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(null, System.Windows.FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsChecked4PropertyChanged, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public bool? IsChecked4
        {
            get
            {
                return GetValue(IsChecked4Property) as bool?;
            }
            set
            {
                SetValue(IsChecked4Property, value);
            }
        }

        #endregion
        #region IsChecked5

        public static readonly System.Windows.DependencyProperty IsChecked5Property = System.Windows.DependencyProperty.Register(nameof(IsChecked5), typeof(bool?), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(null, System.Windows.FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsChecked5PropertyChanged, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public bool? IsChecked5
        {
            get
            {
                return GetValue(IsChecked5Property) as bool?;
            }
            set
            {
                SetValue(IsChecked5Property, value);
            }
        }

        #endregion
        #region IsChecked6

        public static readonly System.Windows.DependencyProperty IsChecked6Property = System.Windows.DependencyProperty.Register(nameof(IsChecked6), typeof(bool?), typeof(CheckBoxListControl),
            new System.Windows.FrameworkPropertyMetadata(null, System.Windows.FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsChecked6PropertyChanged, null, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));
        public bool? IsChecked6
        {
            get
            {
                return GetValue(IsChecked6Property) as bool?;
            }
            set
            {
                SetValue(IsChecked6Property, value);
            }
        }

        #endregion

        #endregion
        #region Private Members

        private bool EventsEnabled = true;

        #region InitializeItems

        private static void InitializeItems(CheckBoxListControl parent)
        {
            parent.StackPanel.Children.Clear();
            if (parent.ItemsSource != null)
            {
                var count = 0;
                foreach (var item in parent.ItemsSource)
                {
                    var checkBox = new CheckBox()
                    {
                        Content = Sidvall.SystemContext.Current.CodeManager.GetPropertyValue(item, parent.DisplayMemberPath),
                        Tag = count.ToString(),
                    };
                    if (!string.IsNullOrWhiteSpace(parent.DisplayMemberPath))
                        checkBox.Content = Sidvall.SystemContext.Current.CodeManager.GetPropertyValue(item, parent.DisplayMemberPath);
                    else
                        checkBox.Content = item.ToString(null);
                    if (count > 0)
                        checkBox.Margin = parent.ItemMargin;
                    if (checkBox.Tag.Equals(parent.IsChecked1))
                        checkBox.IsChecked = true;
                    parent.StackPanel.Children.Add(checkBox);
                    count += 1;
                }
            }
        }

        #endregion
        #region InitializeLabel

        private static void InitializeLabel(CheckBoxListControl parent)
        {
            if (string.IsNullOrEmpty(parent.LabelText))
            {
                parent.Label.Visibility = Visibility.Collapsed;
            }
            else
            {
                parent.Label.Visibility = Visibility.Visible;
            }
        }

        #endregion

        #region OnItemsSourcePropertyChanged

        private static void OnItemsSourcePropertyChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
        {
            var parent = d as CheckBoxListControl;
            if (parent == null)
                return;
            InitializeItems(parent);
        }

        #endregion
        #region OnIsChecked1PropertyChanged

        private static void OnIsChecked1PropertyChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
        {
            var parent = d as CheckBoxListControl;
            if (parent == null)
                return;
            OnIsCheckedPropertyChanged(parent, 0, parent.IsChecked1);
        }

        #endregion
        #region OnIsChecked2PropertyChanged

        private static void OnIsChecked2PropertyChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
        {
            var parent = d as CheckBoxListControl;
            if (parent == null)
                return;
            OnIsCheckedPropertyChanged(parent, 1, parent.IsChecked2);
        }

        #endregion
        #region OnIsChecked3PropertyChanged

        private static void OnIsChecked3PropertyChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
        {
            var parent = d as CheckBoxListControl;
            if (parent == null)
                return;
            OnIsCheckedPropertyChanged(parent, 2, parent.IsChecked3);
        }

        #endregion
        #region OnIsChecked4PropertyChanged

        private static void OnIsChecked4PropertyChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
        {
            var parent = d as CheckBoxListControl;
            if (parent == null)
                return;
            OnIsCheckedPropertyChanged(parent, 3, parent.IsChecked4);
        }

        #endregion
        #region OnIsChecked5PropertyChanged

        private static void OnIsChecked5PropertyChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
        {
            var parent = d as CheckBoxListControl;
            if (parent == null)
                return;
            OnIsCheckedPropertyChanged(parent, 4, parent.IsChecked5);
        }

        #endregion
        #region OnIsChecked6PropertyChanged

        private static void OnIsChecked6PropertyChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
        {
            var parent = d as CheckBoxListControl;
            if (parent == null)
                return;
            OnIsCheckedPropertyChanged(parent, 5, parent.IsChecked6);
        }

        #endregion
        #region OnIsCheckedPropertyChanged

        private static void OnIsCheckedPropertyChanged(CheckBoxListControl parent, int index, bool? value)
        {
            if (parent.StackPanel.Children == null)
                return;
            if (!parent.EventsEnabled)
                return;

            parent.EventsEnabled = false;
            try
            {
                var checkBox = parent.StackPanel.Children[index] as CheckBox;
                checkBox.IsChecked = value;
            }
            finally
            {
                parent.EventsEnabled = true;
            }
        }

        #endregion
        #region OnLabelTextPropertyChanged

        private static void OnLabelTextPropertyChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
        {
            var parent = d as CheckBoxListControl;
            if (parent == null)
                return;
            InitializeLabel(parent);
        }

        #endregion

        #endregion
        #region Events

        #region OnButtonChecked

        private void OnButtonChecked(object sender, RoutedEventArgs e)
        {
            if (!this.EventsEnabled)
                return;
            var checkBox = e.Source as CheckBox;
            if (checkBox == null)
                return;
            var index = checkBox.Tag.ToNullableInt32().Value;
            this.EventsEnabled = false;
            try
            {
                switch (index)
                {
                    case 0:
                        this.IsChecked1 = checkBox.IsChecked;
                        break;
                    case 1:
                        this.IsChecked2 = checkBox.IsChecked;
                        break;
                    case 2:
                        this.IsChecked3 = checkBox.IsChecked;
                        break;
                    case 3:
                        this.IsChecked4 = checkBox.IsChecked;
                        break;
                    case 4:
                        this.IsChecked5 = checkBox.IsChecked;
                        break;
                    case 5:
                        this.IsChecked6 = checkBox.IsChecked;
                        break;
                    default:
                        break;
                }
            }
            finally
            {
                this.EventsEnabled = true;
            }
        }

        #endregion

        #endregion
        #region Constructors

        public CheckBoxListControl()
        {
            InitializeComponent();

            this.StackPanel.AddHandler(ToggleButton.CheckedEvent, new RoutedEventHandler(OnButtonChecked));
            this.StackPanel.AddHandler(ToggleButton.UncheckedEvent, new RoutedEventHandler(OnButtonChecked));
        }

        #endregion
    }
}
